import collections
import copy
import datetime
import uuid
from functools import reduce

import pandas as pd

from server.pao_python.pao.data import (dataframe_to_list, date_to_string,
                                        string_to_date)
from server.pao_python.pao.service.data.mongo_db import (C, F, MongoFilter,
                                                         MongoService, N,
                                                         as_date)

from ...service.buss_pub.bill_manage import (BillManageService, OperationType,
                                             Status, TypeId)
from ...service.common import (GetInformationByIdCard, execute_python,
                               get_current_user_id, get_str_to_age,
                               get_string_time)
from ...service.mongo_bill_service import MongoBillFilter


'''
@Description: In User Settings Edit
@Author: your name
@Date: 2019-09-25 09:48:29
@LastEditTime: 2019-09-25 09:48:29
@LastEditors: your name
'''
'''
说明
 1、服务详情服务
'''


class Tree:
    '定义树类'

    def __init__(self, data):
        self.data = data
        self.children = []

    # def _get(self):
    #     return self.data

    # def _set(self):
    #     return self.data

    def add_child(self, child):
        self.children.append(child)

    def get_children(self):
        return self.children


class Queue():
    '定义队列'

    def __init__(self):
        self.__list = list()

    def is_empty(self):
        return self.__list == []

    def push(self, data):
        self.__list.append(data)

    def pop(self):
        if self.is_empty():
            return False
        return self.__list.pop(0)


class ServiceProductDetailService(MongoService):
    def __init__(self, db_addr, db_port, db_name, db_user, db_pwd, inital_password, session):
        self.db_addr = db_addr
        self.db_port = db_port
        self.db_name = db_name
        self.db_user = db_user
        self.db_pwd = db_pwd
        self.inital_password = inital_password
        self.session = session
        self.bill_manage_server = BillManageService(
            self.db_addr, self.db_port, self.db_name, self.db_user, self.db_pwd, self.inital_password, self.session)

    def get_service_package_detail(self, data):
        '''获取服务包详情'''
        pk_id = data
        _filter = MongoBillFilter()
        _filter.lookup_bill('PT_User', 'organization', 'id', 'org')\
            .add_fields({'org_name': '$org.name'})\
            .add_fields({'org_address': '$org.address'})\
            .match_bill((C('id') == pk_id)).project({'_id': 0, 'org._id': 0})
        res = self.query(_filter, 'PT_Service_Item_Package')
        _filter_comment = MongoFilter()
        _filter_comment.match((C('bill_status') == 'valid') & (
            C('comment_object_id') == pk_id)).project({'_id': 0})
        res_comment = self.query(_filter_comment, "PT_Comment")
        res[0]['comment_list'] = res_comment
        try:
            if res:
                package_price = 0
                for item in res[0].get('service_item'):
                    _filter_item = MongoFilter()
                    _filter_item.match((C('bill_status') == 'valid') & (
                        C('id') == item.get('service_item'))).project({'_id': 0})
                    res_item = self.query(_filter_item, 'PT_Service_Item')
                    if res_item:
                        item['item_name'] = res_item[0]['name']
                        item['valuation_formula'] = res_item[0].get(
                            'valuation_formula')
                    else:
                        item['item_name'] = ''
                        item['valuation_formula'] = ''
                    item_price = 0
                    for option in item.get('service_options'):
                        _filter_option = MongoFilter()
                        _filter_option.match((C('bill_status') == 'valid') & (
                            C('id') == option.get('id'))).project({'_id': 0})
                        res_option = self.query(
                            _filter_option, 'PT_Service_Option')
                        if res_option:
                            option['name'] = res_option[0].get('name')
                            if not option['value']:
                                option['value'] = res_option[0].get(
                                    'default_value')
                            option['option_content'] = res_option[0].get(
                                'option_content')
                    item['value'] = item.get('service_options')[0].get('value')
                    item_price = execute_python(res_item[0].get(
                        'valuation_formula'), item.get('service_options'))
                    package_price += float(item_price)
                res[0]['package_price'] = package_price
                tep = self.cal_option_price(res[0]['service_item'])
                res[0]['service_item'] = tep
                print(res[0]['service_item'])
                return res
            else:
                return {'result': 'fail'}
        except:
            return {'result': 'fail'}

    def get_server_list(self, condition, page, count):
        '''获取服务商列表'''
        keys = ['id']
        values = self.get_value(condition, keys)

        user_id = get_current_user_id(self.session)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']))\
            .lookup_bill('PT_Service_Follow_Collection', 'id', 'business_id', 'follow')\
            .add_fields({'follow_list': self.ao.array_filter('$follow', 'aa', ((F('$aa.type') == 'follow') & (F('$aa.user_id') == user_id)).f)})\
            .project({'_id': 0, 'follow': 0, 'follow_list._id': 0})
        res = self.page_query(_filter, 'PT_User', page, count)
        return res

    def get_server_worker_list(self, condition, page=None, count=None):
        '''获取服务商服务人员列表'''
        keys = ['server_id']
        values = self.get_value(condition, keys)
        # TODO: 服务人员角色id写死
        role_id = '8fa7a328-e355-11e9-98b5-a0a4c57e9ebe'
        _filter = MongoBillFilter()
        _filter.match_bill((C('role_id') == role_id))\
            .match_bill((C('role_of_account_id') == values['server_id']))\
            .lookup_bill('PT_User', 'principal_account_id', 'id', 'server_worker')\
            .project({'_id': 0, 'server_worker._id': 0})
        res = self.page_query(_filter, 'PT_Set_Role', page, count)
        server_worker = []
        if len(res['result']) > 0:
            for i, x in enumerate(res['result']):
                worker_info = x['server_worker']
                data = worker_info[0]['personnel_info']
                if 'date_birth' in data.keys() and data['date_birth'] != '' and data['date_birth'] != None:
                    date_res = get_string_time(data['date_birth'], '%Y-%m-%d')
                    data['date_birth'] = date_res
                    data['age'] = get_str_to_age(date_res)
                server_worker.append(worker_info)
            # for i, x in enumerate(res['result'][0]['server_worker']):
            #     data = x['personnel_info']
            #     if 'date_birth' in data.keys() and data['date_birth'] != '' and data['date_birth'] != None:
            #         date_res = get_string_time(data['date_birth'], '%Y-%m-%d')
            #         data['date_birth'] = date_res
            #         data['age'] = get_str_to_age(date_res)
        res['result'] = server_worker
        return server_worker

    def __handel_data(self, options):
        opt_list = []
        for j in options:
            tep = []
            for i in j['option_content']:
                i.update({'name': j['name']})
                tep.append(i)
            opt_list.append(tep)
        return opt_list

    def __cal_option(self, list1, list2):
        res = []
        for i in list1:
            for j in list2:
                if isinstance(i, list):
                    tep = copy.deepcopy(i)
                    tep.append(j)
                    res.append(tep)
                else:
                    res.append([i, j])
        return res

    def cal_option_price(self, service_item):
        # 计算公式包含在service_item中
        for i in service_item:
            init_data = i['service_options']
            cal_data = self.__handel_data(init_data)

            all_combin = reduce(self.__cal_option, cal_data)
            formula = i['valuation_formula']
            price_data = {}
            for j in all_combin:
                if isinstance(j, dict):
                    j = [j]
                tep_key = [str(t['name'])+'-'+str(t['option_content'])
                           for t in j]
                tep_key_str = '_'.join(tep_key)
                price = execute_python(formula, j, 'option_value')
                price_data[tep_key_str] = price
            i['price'] = price_data
        return service_item

    def get_children_tree(self, pro_id):
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == pro_id))\
            .lookup_bill('PT_User', 'organization_id', 'id', 'org_info')\
            .unwind('org_info')\
            .unwind('org_info.qualification_info', True)\
            .lookup_bill('PT_Qualification_Type', 'org_info.qualification_info.qualification_type_id', 'id', 'qualification_type_info')\
            .lookup_bill('PT_Service_Order', 'id', 'detail.product_id', 'order_info')\
            .match((C("qualification_type_info") == []) | (C('qualification_type_info.name').like('服务评级')))\
            .add_fields({'org_name': '$org_info.name',
                         'org_address': '$org_info.address',
                         'pay_count': self.ao.size('$order_info'),
                         'org_level': '$org_info.qualification_info.qualification_level'})\
            .project({'_id': 0, 'org_info._id': 0, 'qualification_type_info._id': 0, 'order_info._id': 0})
        res = self.query(_filter, 'PT_Service_Product')
        return res

    def get_service_product_package_detail(self, condition, page=None, count=None):
        '''获取服务产品套餐详情'''
        keys = ['id']
        values = self.get_value(condition, keys)
        _filter = MongoBillFilter()
        _filter.match_bill((C('id') == values['id']))\
            .lookup_bill('PT_User', 'organization_id', 'id', 'org_info')\
            .unwind('org_info')\
            .unwind('org_info.qualification_info', True)\
            .lookup_bill('PT_Qualification_Type', 'org_info.qualification_info.qualification_type_id', 'id', 'qualification_type_info')\
            .lookup_bill('PT_Service_Order', 'id', 'detail.product_id', 'order_info')\
            .match((C("qualification_type_info") == []) | (C('qualification_type_info.name').like('服务评级')))\
            .add_fields({'org_name': '$org_info.name',
                         'org_address': '$org_info.address',
                         'pay_count': self.ao.size('$order_info'),
                         'org_level': '$org_info.qualification_info.qualification_level'})\
            .project({'_id': 0, 'org_info._id': 0, 'qualification_type_info._id': 0, 'order_info._id': 0})
        # print(_filter.filter_objects)
        res = self.query(_filter, 'PT_Service_Product')
        # print('222222', res)
        total_price = 0
        try:
            if res:
                porduct_item_list = []
                product_queue = collections.deque()
                product_queue.append(res[0])
                while len(product_queue) != 0:
                    res_f = product_queue.popleft()
                    if res_f.get('service_product'):
                        for product_id_list in res_f.get('service_product'):
                            if product_id_list.get("product_id"):
                                res_child = self.get_children_tree(
                                    product_id_list.get("product_id"))
                                if res_child:
                                    if res_child[0].get('service_product'):
                                        product_queue.append(res_child[0])
                                    else:
                                        if product_id_list.get("remaining_times"):
                                            res_child[0]['remaining_times'] = product_id_list.get(
                                                "remaining_times")
                                        else:
                                            res_child[0]['remaining_times'] = 1
                                        porduct_item_list.append(res_child[0])
                            else:
                                porduct_item_list.append(res_f)
                    else:
                        porduct_item_list.append(res_f)
                item_list = []
                for product_item in porduct_item_list:
                    product_item_price = 0
                    if 'valuation_formula' in product_item and 'service_option' in product_item:
                        if len(product_item['valuation_formula']) > 0 and 'formula' in product_item['valuation_formula'][0]:
                            product_item_price = execute_python(product_item.get('valuation_formula')[0].get(
                                'formula'), product_item.get('service_option'), 'name', 'option_value')
                            total_price += float(product_item_price) * \
                                int(product_item['remaining_times'])
                    if product_item.get('service_item_id'):
                        _filter_item = MongoBillFilter()
                        _filter_item.match_bill(C('id') == product_item.get(
                            'service_item_id')).project({'_id': 0})
                        res_item = self.query(_filter_item, 'PT_Service_Item')
                        if res_item:
                            item_dict = {'item_id': product_item.get('service_item_id'), 'item_name': res_item[0].get(
                                'name'), 'item_price': product_item_price, 'item_option_list': product_item.get('service_option') if product_item.get('service_option') else []}
                            item_list.append(item_dict)
                res[0]['total_price'] = total_price
                res[0]['item_list'] = item_list
                # print(porduct_item_list)
                # res[0]['porduct_item_list'] = porduct_item_list
        except Exception as e:
            print(e)
        return res

    def get_service_product_list(self, condition, page=None, count=None):
        '''获取服务产品列表'''
        keys = ['id', 'servict_product_type', 'organization_id', 'item_list', 'name', 'is_meals']
        values = self.get_value(condition, keys)
        print(values['servict_product_type'])
        _filter = MongoBillFilter()
        _filter.match_bill((C('state') == 1) & (C('is_external') == '1') & (
            C('is_service_item') == 'true') & (C('organization_id') == values['organization_id']) & (
            C('id') == values['id']) & (C('is_meals') == values['is_meals']))\
            .lookup_bill('PT_User', 'organization_id', 'id', 'org_info')\
            .match_bill(C('org_info.name').like(values['name']) | (C('name').like(values['name'])))\
            .lookup_bill('PT_Service_Item', 'service_item_id', 'id', 'item')\
            .add_fields({'item': self.ao.array_elemat('$item', 0)})\
            .match_bill(C('item.item_type').inner(values['item_list']))\
            .match_bill(C('item.item_type') == values['servict_product_type'])\
            .add_fields({'org_info': '$org_info'})\
            .lookup_bill('PT_Service_Order', 'id', 'detail.product_id', 'order_info')\
            .add_fields({'pay_count': self.ao.size('$order_info'), 'total_price': '$service_package_price'})\
            .lookup_bill('PT_Service_Order_Comment', 'id', 'product_id', 'comment')\
            .add_fields({'comment_all': self.ao.summation('$comment.service_quality')})\
            .add_fields({'length': self.ao.size('$comment')})\
            .add_fields({'comment_avg': self.ao.floor(self.ao.switch([self.ao.case(((F('length') == 0)), 0)], (F('comment_all').__truediv__('$length')).f))})\
            .project({'_id': 0, 'org_info._id': 0, 'item._id': 0, 'order_info._id': 0, 'comment._id': 0})
        # n_page = page
        # n_count = count
        if 'sort' in condition and condition['sort'] != None and 'sort' in condition and condition['num'] != None:
            if condition['sort'] == '销量':
                _filter.sort({'pay_count': condition['num']})
            elif condition['sort'] == '价格':
                _filter.sort({'service_package_price': condition['num']})
            else:
                _filter.sort({'create_date': -1})
        res = self.page_query(_filter, 'PT_Service_Product', page, count)
        # if res.get('result'):
        #     for product in res['result']:
        #         pruduct_detail = self.get_service_product_package_detail(
        #             {'id': product.get('id')})
        #         product['total_price'] = 0
        #         if len(pruduct_detail) > 0 and 'total_price' in pruduct_detail[0]:
        #             product['total_price'] = pruduct_detail[0].get(
        #                 'total_price')
        #         if len(pruduct_detail) > 0 and 'pay_count' in pruduct_detail[0]:
        #             product['pay_count'] = pruduct_detail[0].get('pay_count')
        # if 'sort' in condition and condition['sort'] != None:
        #     if condition['sort'] == '销量':
        #         sort_key = 'pay_count'
        #     if condition['sort'] == '价格':
        #         sort_key = 'total_price'
        #     for i in range(len(res['result'])-1):
        #         for j in range(len(res['result'])-1-i):
        #             if res['result'][j][sort_key] > res['result'][j+1][sort_key]:
        #                 res['result'][j], res['result'][j +
        #                                                 1] = res['result'][j+1], res['result'][j]
        #     first = (int(page)-1) * int(count)
        #     ne = int(count) + int(page)
        #     res['result'] = res['result'][first:ne]
        return res

    def get_service_product_item_package_list(self, condition, page=None, count=None):
        '''获取服务产品/服务套餐列表'''
        keys = ['id', 'servict_product_type', 'organization_id', 'item_list', 'name', 'is_meals', 'is_service_item']
        values = self.get_value(condition, keys)
        print(values['servict_product_type'])
        _filter = MongoBillFilter()
        _filter.match_bill((C('state') == 1) & (C('is_external') == '1') & (
            C('is_service_item') == values['is_service_item']) & (C('organization_id') == values['organization_id']) & (
            C('id') == values['id']) & (C('is_meals') == values['is_meals']))\
            .lookup_bill('PT_User', 'organization_id', 'id', 'org_info')\
            .match_bill(C('org_info.name').like(values['name']) | (C('name').like(values['name'])))\
            .lookup_bill('PT_Service_Item', 'service_item_id', 'id', 'item')\
            .lookup_bill('PT_Service_Type', 'item.item_type', 'id', 'type')\
            .match(C('item.item_type').inner(values['item_list']) & C('item.item_type') == values['servict_product_type'])\
            .add_fields({'org_info': '$org_info'})\
            .lookup_bill('PT_Service_Order', 'id', 'detail.product_id', 'order_info')\
            .add_fields({'pay_count': self.ao.size('$order_info'), 'total_price': '$service_package_price'})\
            .project({'_id': 0, 'org_info._id': 0, 'item._id': 0, 'order_info._id': 0, 'type._id': 0})
        # n_page = page
        # n_count = count

        # 获取当前的登录的用户ID的组织机构ID，在我的发布需要用到
        if 'org_id' in condition and condition['org_id'] == True:
            user_id = get_current_user_id(self.session)

            if user_id != False:
                _filter_set_role = MongoBillFilter()
                _filter_set_role.match_bill((C('principal_account_id') == user_id))\
                    .project({'_id': 0})
                res_set_role = self.query(_filter_set_role, 'PT_Set_Role')
                if len(res_set_role) > 0:
                    _filter.match_bill((C('organization_id') == res_set_role[0]['role_of_account_id']))

        if 'sort' in condition and condition['sort'] != None and 'num' in condition and condition['num'] != None:
            if condition['sort'] == '销量':
                _filter.sort({'pay_count': condition['num']})
            elif condition['sort'] == '价格':
                _filter.sort({'service_package_price': condition['num']})
            else:
                _filter.sort({'create_date': -1})
        res = self.page_query(_filter, 'PT_Service_Product', page, count)
        # if res.get('result'):
        #     for product in res['result']:
        #         pruduct_detail = self.get_service_product_package_detail(
        #             {'id': product.get('id')})
        #         product['total_price'] = 0
        #         if len(pruduct_detail) > 0 and 'total_price' in pruduct_detail[0]:
        #             product['total_price'] = pruduct_detail[0].get(
        #                 'total_price')
        #         if len(pruduct_detail) > 0 and 'pay_count' in pruduct_detail[0]:
        #             product['pay_count'] = pruduct_detail[0].get('pay_count')
        # if 'sort' in condition and condition['sort'] != None:
        #     if condition['sort'] == '销量':
        #         sort_key = 'pay_count'
        #     if condition['sort'] == '价格':
        #         sort_key = 'total_price'
        #     for i in range(len(res['result'])-1):
        #         for j in range(len(res['result'])-1-i):
        #             if res['result'][j][sort_key] > res['result'][j+1][sort_key]:
        #                 res['result'][j], res['result'][j +
        #                                                 1] = res['result'][j+1], res['result'][j]
        #     first = (int(page)-1) * int(count)
        #     ne = int(count) + int(page)
        #     res['result'] = res['result'][first:ne]
        return res
